Skip to content

Conversation

@shajrawi
Copy link

Consider a class ‘C’ with distinct fields ‘A’ and ‘B’

And consider we are accessing C.A and C.B inside a loop

LICM well not hoist the exclusivity checking outside of the loop because isDistinctFrom(C.A, C.B) returns false.

This is because the helper function bails if isUniquelyIdentified returns false (which is the case in class kinds)

Same with all other potential access enforcement optimizations.

This PR resolves that

radar rdar://problem/43403553

@shajrawi
Copy link
Author

@swift-ci Please test

@shajrawi shajrawi requested a review from atrick August 22, 2018 06:39
@shajrawi
Copy link
Author

@atrick Can you please review?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure that this really checks if the begin_accesses are moved out of the loop?
There could be basic block headers between the checked lines

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes: see TEST3 above these lines: it is the debug output of LICM - saying that we hoisted the begin_accesses auto of the loop.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And the checks, after the new support, turned from dynamic to static.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't you also test the writeArr function?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The accesses to 'A' and 'B' in writeArr are begin_unpaired_access which we cannot (currently) hoist or merge (for safety) - if we end up supporting those in the future (which, from what I saw so far, is not high on our list and is too risky) then we can add such a lit test of course

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is also why I did not add such a write function to lit test, but it is part of the benchmark.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume the point of this benchmark is to check if the access checks are moved out of the loops. IMO, it's not required to have a benchmark for this, because this can be easily checked with a lit test - as you do.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I discussed the inclusion of this benchmark with @atrick yesterday, was not sure if we should include it or not, decided to add it to the unstable / exclusivity benchmark package - which we do not run by default.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's nice to have a separate data point in the public benchmark suite for some part of a larger benchmark that we care about. On the other hand, if there's nothing unique or interesting about the code aside from the exclusivity check, then it doesn't really add value.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't you just use AliasAnalysis::isNoAlias for this check?
Internally it performs the same check with projection paths as you do here + several other checks. So it is more accurate.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we certainly could. it is higher overhead of course: we know for sure we have two address projections and just need to check their projection paths, which is part of isNoAlias as you say. I looked for other uses of both in the optimizer, for consistency, from what I saw, when we have a similar situation ( LoadStoreOpt and ARC ) we called hasNonEmptySymmetricDifference directly. but I can change that.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i.e. the extra checks / code paths are known to be false + we are fetching AliasAnalysis / tying it to memory access utilities, unlike load store utilities which avoided that, but it should work

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just added Alais Analysis on my machine: we don't have access to a pass manager in accessed storage, which means we have to create AA outside and pass it in to the class' constructor, polluting the entire code and call sites to accessed storage for no change in behavior, it also looks ugly by forcing an analysis from the SIL Optimizer library into a SIL library utility

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A pass could use AliasAnalysis, and we could teach AliasAnalysis about AccessedStorage. As it is, the MemAccessUtils check will be missing TBAA and escape analysis. I would want a different AliasAnalysis entry point for AccessedStorage though. Almost all of the existing AliasAnlysis code is irrelevant, so it would be very inefficient and hard to reason about what really happens in the formal access case.

Copy link
Contributor

@atrick atrick left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. A few comments below.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's nice to have a separate data point in the public benchmark suite for some part of a larger benchmark that we care about. On the other hand, if there's nothing unique or interesting about the code aside from the exclusivity check, then it doesn't really add value.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (getKind() != Class || other.getKind() != Class)
  return false

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A pass could use AliasAnalysis, and we could teach AliasAnalysis about AccessedStorage. As it is, the MemAccessUtils check will be missing TBAA and escape analysis. I would want a different AliasAnalysis entry point for AccessedStorage though. Almost all of the existing AliasAnlysis code is irrelevant, so it would be very inefficient and hard to reason about what really happens in the formal access case.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand what's happening here. We have the notion equivalence for two AccessedStorage locations. That notion of equivalence needs to be consistent with the DenseMap properties. hasIdenticalBase is the way to do that. If two storage locations are equivalent, then it wouldn't make sense to also check isDistinctFrom.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad - reverted to previous.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, but recomputing the projection every time you query a storage location seems more expensive. The idea behind caching the projection is that the AccessedStorage are in turn cached in a map of accesses, so you never need to recompute them.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed so Projection is not lazily computed.

@swiftlang swiftlang deleted a comment from swift-ci Aug 22, 2018
@swiftlang swiftlang deleted a comment from swift-ci Aug 23, 2018
Consider a class ‘C’ with distinct fields ‘A’ and ‘B’

And consider we are accessing C.A and C.B inside a loop

LICM well not hoist the exclusivity checking outside of the loop because isDistinctFrom(C.A, C.B) returns false.

This is because the helper function bails if isUniquelyIdentified returns false (which is the case in class kinds)

Same with all other potential access enforcement optimizations.

This PR resolves that
@swiftlang swiftlang deleted a comment from swift-ci Aug 23, 2018
@shajrawi
Copy link
Author

@swift-ci Please test

@shajrawi shajrawi merged commit 2e12d6b into swiftlang:master Aug 23, 2018
@palimondo
Copy link
Contributor

The DistinctClassFieldAccesses benchmark is never run... is packed into an unrelated file with benchmarks for Existential, is formatted very... unconventionally and has too low of a workload. IMO this one really doesn't pass muster. @shajrawi, @atrick can you be more specific about its intended purpose outside of what is already covered by lit test as @eeckstein asked? Maybe we can salvage this somehow. Otherwise I'll remove it.

@atrick
Copy link
Contributor

atrick commented Nov 5, 2018 via email

palimondo added a commit to palimondo/swift that referenced this pull request Feb 7, 2019
Benchmark DistinctClassFieldAccesses was added in a strange place…
See https://github.com/apple/swift/pull/18892/files#r212038958

Per discussion in in swiftlang#18892 (comment)
I’m moving it to the extremely similar `ArrayInClass`, while fixing its workload size (and loop pattern) to make it relatively comparable.
@shajrawi shajrawi deleted the class_paths branch April 12, 2019 22:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants